package frontend.search.controller;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


import backend.paging.Paging;
import backend.product.manager.ProductAttributeManager;
import backend.product.manager.ProductManager;

import com.opensymphony.xwork2.ActionSupport;

import core.attribute.model.Attribute;
import core.category.helper.CategoryPath;
import core.category.model.Category;
import core.product.model.Product;
import core.product.model.ProductOwner;
import core.product.model.ProductType;
import frontend.category.manager.CategoryManager;
import frontend.search.manager.SearchManager;

public class SearchAction extends ActionSupport 
{
	private static final long serialVersionUID = 14343L;
	private SearchManager searchManager ;
	private ProductManager pm;
	private CategoryManager cm ;
	private String searchkey ;
	private List<Product> products ;
	private List<Long> productIds ;
	private Map<ProductType,Integer> producttype ;
	private Map<String,Integer> ownerCount;
	private Map<Attribute,Integer> featuresFilter ;
	private Map<Attribute,Integer> moreFilter ;
	private Map<String,Integer> suggestionMap ;
	int reviewCount;
	int rating;
	private String attractions ;
	private String amenities ;
	private String productType ;
	private String owner ;
	private boolean iscategory ;
	private Category category ;
	private Map<Long,String> path;
	private Map<Category,Integer> subCateegory ;
	// set these 3 variable for paging
	private int pageSize ;
	private int p ;
	private List<String> pageHtml ;
	
	public SearchAction()
	{
		searchManager =  new SearchManager();
		pm = new ProductManager();
		cm = new CategoryManager();
	}
	public String getProductAttribute(Long uuid,String productAttribute)
	{
		ProductAttributeManager pam = new ProductAttributeManager();
		ProductManager pm = new ProductManager();
		Product p = pm.getProductByUuid(uuid);
		String attribute = pam.getSingleValueAttributeByName(p, productAttribute);
		return attribute;
	}
	public int getProductReviewCount(Long uuid)
	{
		int reviewCount;
		ProductAttributeManager pam = new ProductAttributeManager();
		ProductManager pm = new ProductManager();
		Product p = pm.getProductByUuid(uuid);
		reviewCount = pam.getReviewCount(p);
		return reviewCount;
	}
	public int getProductRating(Long uuid)
	{
		int rating;
		ProductAttributeManager pam = new ProductAttributeManager();
		ProductManager pm = new ProductManager();
		Product p = pm.getProductByUuid(uuid);
		rating = pam.getRating(p);
		return rating;
	}
	public String suggestion()
	{
		this.setSuggestionMap(searchManager.getSuggestionSearch(this.searchkey));
		return SUCCESS ; 
	}
	public String filter()
	{
		// read object from cache....
		try
		{
			String fileName="search_"+this.searchkey ;
			FileInputStream fin = new FileInputStream(fileName);
			ObjectInputStream ois = new ObjectInputStream(fin);
			this.products = (List<Product>) ois.readObject();
			
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		catch(ClassNotFoundException cnfe)
		{
			cnfe.printStackTrace();
		}
		String attractions = this.getAttractions();
		String amenities = this.getAmenities();
		String productType = this.getProductType();
		String owner = this.getOwner();
		String queryPart = searchManager.getQueryPart(this.products);
		int filterApplied = 0; 
		if(attractions != null && !(attractions.trim().equals("")))
		{
			String qryCol = "";
			String tableName = "attractions_filter_index";
			String[] tempFilter;
			String delimiter = ",";
			tempFilter = attractions.split(delimiter);
			for(int i =0; i < tempFilter.length ; i++)
			{
				if(tempFilter[i]!= null && tempFilter[i].trim() != "")
				{
					String col = "c"+tempFilter[i] ;
					qryCol = qryCol  + col + " = 1 and " ;
				}
			}
			String qry = "select productid from "+tableName+" where " + qryCol + " productid in " + queryPart;
			List<Long> pidLst = searchManager.applyFilter(qry);
			queryPart = searchManager.getQueryPartFromId(pidLst);
			this.setProductIds(pidLst);
			filterApplied = 1;
		}
		if(amenities != null && !(amenities.trim().equals("")))
		{
			String qryCol = "";
			String tableName = "amenities_filter_index";
			String[] tempFilter;
			String delimiter = ",";
			tempFilter = amenities.split(delimiter);
			for(int i =0; i < tempFilter.length ; i++)
			{
				if(tempFilter[i]!= null && tempFilter[i].trim() != "")
				{
					String col = "c"+tempFilter[i] ;
					qryCol = qryCol  + col + " = 1 and " ;
				}
			}
			String qry = "select productid from "+tableName+" where " + qryCol + " productid in " + queryPart;
			List<Long> pidLst = searchManager.applyFilter(qry);
			queryPart = searchManager.getQueryPartFromId(pidLst);
			this.setProductIds(pidLst);
			filterApplied = 1;
		}
		if(productType != null && !(productType.trim().equals("")))
		{
			String qryCol = "";
			String tableName = "product_type_index";
			String[] tempFilter;
			String delimiter = ",";
			tempFilter = productType.split(delimiter);
			for(int i =0; i < tempFilter.length ; i++)
			{
				if(tempFilter[i]!= null && tempFilter[i].trim() != "")
				{
					String col = "c"+tempFilter[i] ;
					qryCol = qryCol  + col + " = 1 and " ;
				}
			}
			String qry = "select productid from "+tableName+" where " + qryCol + " productid in " + queryPart;
			List<Long> pidLst = searchManager.applyFilter(qry);
			queryPart = searchManager.getQueryPartFromId(pidLst);
			this.setProductIds(pidLst);
			filterApplied = 1;
		}
		if(filterApplied == 1)
		{
			List<Product> pLst = new ArrayList<Product>();
			Iterator<Long> pids = this.getProductIds().iterator();
			while(pids.hasNext())
			{
				Product p = pm.getProductByUuid(pids.next());
				pLst.add(p);
			}
			this.setProducts(pLst);
		}
		
		if(owner != null && !(owner.trim().equals("")))
		{
			String[] tempFilter = owner.split(",");
			for(int i =0; i < tempFilter.length ; i++)
			{
				if(tempFilter[i]!= null && tempFilter[i].trim() != "")
				{
					List<Product> filteredProd = new ArrayList<Product>();
					Iterator<Product> prodItr = this.getProducts().iterator();
					String ownerFilter = tempFilter[i];
					while(prodItr.hasNext())
					{
						Product p = prodItr.next();
						ProductOwner po =  pm.getProductOwner(p) ;
						if(po != null)
						{
							String managedBy = po.getManagedBy();
							if(managedBy != null && !(managedBy.trim().equals("")))
							{
								if(managedBy.equals(ownerFilter))
								{
									filteredProd.add(p);
								}
							}
						}
					}
					this.setProducts(filteredProd);
				}
				
			}
			
		}
		queryPart = searchManager.getQueryPart(this.getProducts());
		
		this.producttype=searchManager.getProductTypeCountMap(queryPart);
		this.setOwnerCount(searchManager.getManagerCount(queryPart));
		this.setFeaturesFilter(searchManager.getAttributeFilter(queryPart,"Amenities"));
		this.setMoreFilter(searchManager.getAttributeFilter(queryPart,"Attractions"));
		return SUCCESS ;
	}
	public String execute() 
	{
		this.searchkey = this.getSearchkey();
		Category category = cm.getCategoryByName(this.searchkey);
		if(category != null)
		{
			this.products = new ArrayList<Product>();
			this.products.addAll(category.getProducts()) ;
			this.setIscategory(true);
			this.setCategory(category);
			CategoryPath cp = new CategoryPath(this.category.getPath());
			this.path = cp.getPathMap();
			this.setSubCateegory(cm.getSubCategoryListCont(category));
		}
		else
		{
			this.products = searchManager.getSimpleSearchResult(this.searchkey);
		}
		// write product iterator to file
		try
		{
			String fileName="search_"+this.searchkey ;
			FileOutputStream fout = new FileOutputStream(fileName);
			ObjectOutputStream oos = new ObjectOutputStream(fout);
			oos.writeObject(this.products);
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		if(this.getPageSize() == 0)
		{
			this.setPageSize(10);
		}
		String queryPart = searchManager.getQueryPart(this.products);
		Paging paging = new Paging<Product>();
		int listSize = this.products.size();
		this.products = paging.getPageList(pageSize, this.products, p);
		this.setPageHtml(paging.getPageHtml(p, pageSize, listSize));
		
		this.producttype=searchManager.getProductTypeCountMap(queryPart);
		this.setOwnerCount(searchManager.getManagerCount(queryPart));
		this.setFeaturesFilter(searchManager.getAttributeFilter(queryPart,"Amenities"));
		this.setMoreFilter(searchManager.getAttributeFilter(queryPart,"Attractions"));
		return SUCCESS ;
	}

	public String getSearchkey() {
		return searchkey;
	}
	public Map<ProductType,Integer> getProducttype() {
		return producttype;
	}
	public void setProducttype(Map<ProductType,Integer> producttype) {
		this.producttype = producttype;
	}
	public void setSearchkey(String searchkey) {
		this.searchkey = searchkey;
	}
	public List<Product> getProducts() {
		return products;
	}
	public void setProducts(List<Product> products) {
		this.products = products;
	}
	public Map<String,Integer> getOwnerCount() {
		return ownerCount;
	}
	public void setOwnerCount(Map<String,Integer> ownerCount) {
		this.ownerCount = ownerCount;
	}
	public Map<Attribute, Integer> getFeaturesFilter() {
		return featuresFilter;
	}
	public void setFeaturesFilter(Map<Attribute, Integer> featuresFilter) {
		this.featuresFilter = featuresFilter;
	}
	public Map<Attribute, Integer> getMoreFilter() {
		return moreFilter;
	}
	public void setMoreFilter(Map<Attribute, Integer> moreFilter) {
		this.moreFilter = moreFilter;
	}
	public String getAttractions() {
		return attractions;
	}
	public void setAttractions(String attractions) {
		this.attractions = attractions;
	}
	public String getAmenities() {
		return amenities;
	}
	public void setAmenities(String amenities) {
		this.amenities = amenities;
	}
	public boolean selectedFilter(String as,String uuid)
	{
		if(as == null)
		{
			return false ;
		}
		String newUuid = uuid + "";
		if(as.equals(newUuid))
		{
			return true ;
		}
		if(as.indexOf(newUuid) >= 0)
		{
			return true ;
		}
		return false ;
	}
	public boolean selectedFilter(String as,Long uuid)
	{
		if(as == null)
		{
			return false ;
		}
		String newUuid = uuid + "";
		return selectedFilter(as,newUuid);
	}
	public String getProductType() {
		return productType;
	}
	public void setProductType(String productType) {
		this.productType = productType;
	}
	public String getOwner() {
		return owner;
	}
	public void setOwner(String owner) {
		this.owner = owner;
	}
	public List<Long> getProductIds() {
		return productIds;
	}
	public void setProductIds(List<Long> productIds) {
		this.productIds = productIds;
	}
	public Map<String, Integer> getSuggestionMap() {
		return suggestionMap;
	}
	public void setSuggestionMap(Map<String, Integer> suggestionMap) {
		this.suggestionMap = suggestionMap;
	}
	public boolean isIscategory() {
		return iscategory;
	}
	public void setIscategory(boolean iscategory) {
		this.iscategory = iscategory;
	}
	public Category getCategory() {
		return category;
	}
	public void setCategory(Category category) {
		this.category = category;
	}
	/**
	 * @return the path
	 */
	public Map<Long, String> getPath() {
		return path;
	}
	/**
	 * @param path the path to set
	 */
	public void setPath(Map<Long, String> path) {
		this.path = path;
	}
	/**
	 * @return the subCateegory
	 */
	public Map<Category,Integer> getSubCateegory() {
		return subCateegory;
	}
	/**
	 * @param subCateegory the subCateegory to set
	 */
	public void setSubCateegory(Map<Category,Integer> subCateegory) {
		this.subCateegory = subCateegory;
	}
	/**
	 * @return the pageSize
	 */
	public int getPageSize() {
		return pageSize;
	}
	/**
	 * @param pageSize the pageSize to set
	 */
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	/**
	 * @return the p
	 */
	public int getP() {
		return p;
	}
	/**
	 * @param p the p to set
	 */
	public void setP(int p) {
		this.p = p;
	}
	/**
	 * @return the pageHtml
	 */
	public List<String> getPageHtml() {
		return pageHtml;
	}
	/**
	 * @param pageHtml the pageHtml to set
	 */
	public void setPageHtml(List<String> pageHtml) {
		this.pageHtml = pageHtml;
	}
	
}
